﻿using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace Smart.Model
{
    public class Buffer
    {
        public Vector3[] buffer;
        public Vector2[] uvs;
        public int index;
        public long guid;

        public void DrawRect(int offset,int x,int y,int w,int h)
        {
            buffer[offset] = new Vector3(x, y, 0);
            buffer[offset + 1] = new Vector3(x, y + h, 0);
            buffer[offset + 2] = new Vector3(x + w, y + h, 0);
            buffer[offset + 3] = new Vector3(x + w, y, 0);
        }

        public void DrawUVRect(int offset, float x, float y, float w, float h)
        {
            uvs[offset] = new Vector3(x, y, 0);
            uvs[offset + 1] = new Vector3(x, y + h, 0);
            uvs[offset + 2] = new Vector3(x + w, y + h, 0);
            uvs[offset + 3] = new Vector3(x + w, y, 0);
        }
    }

    public static class BufferPool
    {
        static Stack<Buffer>[] mPooledBuffers = new Stack<Buffer>[18];
        static long ms_guid = 0x354dee;
        static Dictionary<long, Buffer> mActivedBuffers = new Dictionary<long, Buffer>(1024);
        public static long ms_pooled_bytes
        {
            get;private set;
        }

        public static Buffer Get(this Buffer src,int bufferLength)
        {
            if (bufferLength < 4)
                bufferLength = 4;

            bufferLength = bufferLength >> 2 << 2;

            if(null != src)
            {
                if (src.buffer.Length >= bufferLength)
                    return src;

                src.Put();
            }

            for (int i = 0; i < 17; ++i)
            {
                if((1 << i) >= bufferLength)
                {
                    var pool = mPooledBuffers[i];
                    if (null == pool)
                    {
                        pool = new Stack<Buffer>(128);
                    }

                    if (pool.Count > 0)
                        return pool.Pop();

                    long guid = ++ms_guid;
                    var buffer = new Buffer
                    {
                        buffer = new Vector3[bufferLength],
                        uvs = new Vector2[bufferLength],
                        index = i,
                        guid = guid,
                    };

                    ms_pooled_bytes += bufferLength;

                    mActivedBuffers.Add(guid, buffer);
                    return buffer;
                }
            }

            return null;
        }

        public static void Put(this Buffer buffer)
        {
            if(mActivedBuffers.Remove(buffer.guid))
            {
                mPooledBuffers[buffer.index].Push(buffer);
            }
            else
            {
                Smart.Model.Logger.LogError($"Recycle repeated for {buffer.guid}");
            }
        }
    }
}